﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using ESRI.ArcGIS.Client.Geometry;

using Microsoft.Surface;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
using Microsoft.Surface.Presentation.Input;

namespace GISforTT_API
{
    /// <summary>
    /// Interaction logic for GhostFrame. 
    /// Represents the reference area for an open MapFrame.
    /// It shadows the current viewing area of an open MapFrame
    /// onto the BackgroundMapLayer in reference to the background
    /// map.
    /// </summary>
    public partial class GhostFrame : ScatterViewItem
    {
        ArcGisMap parentMap;
        Envelope mapExtent;
        MapFrame linkedMapFrame;

        public Envelope Extent
        {
            get
            {
                return mapExtent;
            }
        }

        public MapFrame LinkedMapFrame
        {
            set
            {
                linkedMapFrame = value;
            }
        }

        public SolidColorBrush Color
        {
            get
            {
                return (SolidColorBrush)ghostRectangle.Fill;
            }
        }

        /// <summary>
        /// Constructor for GhostFrame.

        /// Takes in a reference to the map where the 
        /// frame will be position, the evelope (extent) of
        /// the map that the frame covers, and the colour of
        /// the frame.
        /// </summary>
        /// <param name="backgroundMap">a reference to the background map where the frame will be position</param>
        /// <param name="mapEnvelope">the evelope (extent) of the map that the frame covers</param>
        /// <param name="color">the colour of the frame.</param>
        public GhostFrame(ArcGisMap backgroundMap, Envelope mapEnvelope, SolidColorBrush color) 
        {
            InitializeComponent();

            //disable the flicking gesture
            this.Deceleration = double.NaN;

            parentMap = backgroundMap;
            mapExtent = mapEnvelope;

            ghostRectangle.Fill = color;
            ghostRectangle.Opacity = 0.5;

            MapPoint mpt1 = new MapPoint(mapEnvelope.XMin, mapEnvelope.YMax);
            MapPoint mpt4 = new MapPoint(mapEnvelope.XMax, mapEnvelope.YMin);
            // convert map points into screen coordinates
            Point pt1 = (parentMap).Map.MapToScreen(mpt1);
            Point pt2 = (parentMap).Map.MapToScreen(mpt4);

            this.Height = Math.Abs(pt1.Y - pt2.Y);
            this.Width = Math.Abs(pt1.X - pt2.X);

            Center = new Point(pt1.X + (pt2.X - pt1.X) / 2, pt1.Y + (pt2.Y - pt1.Y) / 2);
        }

        /// <summary>
        /// Updates the current position of the frame according
        /// to the viewing area of its associated MapFrame.
        /// </summary>
        /// <param name="mapEnvelope">new map envelope</param>
        public void UpdatePosition(Envelope mapEnvelope)
        {
            mapExtent = mapEnvelope;

            /**
             * GhostFrame Point Structure
             * ---------------------------
             *   mpt1                   
             *     + --------------------- +
             *     |                       |
             *     |                       |
             *     |                       |       |
             *     |      Ghost Frame      |       |\
             *     |                       |      _|
             *     |                       |       | 
             *     |                       |       | North
             *     + --------------------- +
             *                             mpt2
             * 
             */
            MapPoint mpt1 = new MapPoint(mapEnvelope.XMin, mapEnvelope.YMax);
            MapPoint mpt2 = new MapPoint(mapEnvelope.XMax, mapEnvelope.YMin);
            mapExtent = new Envelope(mpt1, mpt2);
            // convert map points into screen coordinates
            Point pt1 = (parentMap).Map.MapToScreen(mpt1);
            Point pt2 = (parentMap).Map.MapToScreen(mpt2);

            this.Height = Math.Abs(pt1.Y - pt2.Y);
            this.Width = Math.Abs(pt1.X - pt2.X);

            // calculate the centre point of where the ghost frame should be
            Center = new Point(pt1.X + (pt2.X - pt1.X) / 2, pt1.Y + (pt2.Y - pt1.Y) / 2);           
            
        }

        private void GhostFrameManipulated()
        {
            var xMin = this.Center.X - (this.Width / 2);
            var xMax = this.Center.X + (this.Width / 2);
            var yMin = this.Center.Y - (this.Height / 2);
            var yMax = this.Center.Y + (this.Height / 2);

            MapPoint mpt1 = (parentMap).Map.ScreenToMap(new Point(xMax, yMax));
            MapPoint mpt2 = (parentMap).Map.ScreenToMap(new Point(xMin, yMin));

            Envelope mapEnv = new Envelope(mpt1, mpt2);

            linkedMapFrame.UpdateMap(mapEnv);
        }

        private void ScatterViewItem_ContainerManipulationStarted(object sender, ContainerManipulationStartedEventArgs e)
        {
            GhostFrameManipulated();
        }

        private void ScatterViewItem_ContainerManipulationDelta(object sender, ContainerManipulationDeltaEventArgs e)
        {
            GhostFrameManipulated();
        }

        private void ScatterViewItem_ContainerManipulationCompleted(object sender, ContainerManipulationCompletedEventArgs e)
        {
            GhostFrameManipulated();
        }

    }
}
